package cn.t.facade.android;


import cn.t.constants.CommonConstants;
import cn.t.converter.android.DeviceAndroidConfigDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.core.facade.FacadeImpl;
import cn.t.dto.android.DeviceAndroidConfigDTO;
import cn.t.enums.ReleaseTypeEnum;
import cn.t.enums.order.ErrorEnum;
import cn.t.model.android.DeviceAndroidConfigDO;
import cn.t.model.device.DeviceConfigRowDO;
import cn.t.model.device.DeviceDO;
import cn.t.model.user.CustomerFirmDO;
import cn.t.request.DeviceAndroidConfigEditReq;
import cn.t.service.device.DeviceAndroidConfigService;
import cn.t.service.device.DeviceConfigRowService;
import cn.t.service.device.DeviceService;
import cn.t.service.user.CustomerFirmService;
import cn.t.utils.JsonUtil;
import cn.t.utils.SignUtil;
import cn.t.vo.FunctionConfigDetailVO;
import cn.t.vo.andriod.AndroidConfigVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 安卓功能配置表(DeviceAndroidConfig)服务编排
 *
 * @author t
 * @since 2024-05-24 10:19:33
 */
@Slf4j
@Service
@AllArgsConstructor
public class DeviceAndroidConfigFacade extends FacadeImpl<DeviceAndroidConfigDTO, DeviceAndroidConfigDO, DeviceAndroidConfigDTOConverter, DeviceAndroidConfigService> {

    private final DeviceConfigRowService deviceConfigRowService;
    private final DeviceService deviceService;
    private final CustomerFirmService customerFirmService;

    @Override
    public boolean add(DeviceAndroidConfigDTO dto) {
        // 校验重复数据
        DeviceAndroidConfigDO configDO = service.getConfig(dto.getKey(), dto.getValue());
        if (configDO != null) {
            throw new BizException(ErrorEnum.DATA_ALREADY_EXISTS, String.format(ErrorEnum.DATA_ALREADY_EXISTS.getMessage(), dto.getKey()));
        }

        return this.service.add(this.converter.dto2Model(dto));
    }

    public FunctionConfigDetailVO detail(Long configId, Boolean isEdit) {

        // 查询功能配置信息
        DeviceAndroidConfigDO androidConfigDO = this.service.findById(configId);
        if (androidConfigDO == null) {
            return null;
        }

        FunctionConfigDetailVO functionConfigDetailVO = this.converter.do2DetailVo(androidConfigDO);

        // 查询配置的设备id信息
        List<DeviceConfigRowDO> deviceConfigRows = deviceConfigRowService.getConfigRows(androidConfigDO.getId());

        // 配置的设备
        List<Long> deviceIds = deviceConfigRows.stream().map(DeviceConfigRowDO::getDeviceId).collect(Collectors.toList());
        List<DeviceDO> devices = deviceService.getDevices(null, null, null, CommonConstants.ONE);
        if (Boolean.TRUE.equals(isEdit)) {
            // 拼装编辑页面设备信息
            List<CustomerFirmDO> allFirms = this.customerFirmService.findByModel(new CustomerFirmDO(), CommonConstants.ZERO, Integer.MAX_VALUE, null, null);

            List<FunctionConfigDetailVO.Firm> firms = new ArrayList<>();
            allFirms.forEach(firm -> {
                // 公司拥有的设备
                List<DeviceDO> firmDevices = devices.stream().filter(f -> firm.getId().equals(f.getFirmId())).collect(Collectors.toList());
                List<FunctionConfigDetailVO.MainDevice> deviceVOs = firmDevices.stream().map(f -> this.converter.deviceDo2ConfigDeviceVo(f, configId)).collect(Collectors.toList());
                // 标记已选设备
                deviceVOs.forEach(f -> {
                    f.setKey(String.valueOf(firm.getId()) + f.getDeviceId());
                    if (deviceIds.contains(f.getDeviceId())) {
                        f.setSelected(true);
                    }
                });
                FunctionConfigDetailVO.Firm firmVO = new FunctionConfigDetailVO.Firm(String.valueOf(firm.getId()), firm.getId(), firm.getFirmName(), deviceVOs);
                firms.add(firmVO);
            });

            functionConfigDetailVO.setFirms(firms);
        } else {
            // 拼装详情页面设备信息
            List<FunctionConfigDetailVO.MainDevice> deviceVOs = devices.stream().filter(f -> deviceIds.contains(f.getId()))
                    .map(f -> this.converter.deviceDo2ConfigDeviceVo(f, configId)).collect(Collectors.toList());
            functionConfigDetailVO.setDevices(deviceVOs);
        }

        return functionConfigDetailVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean config(DeviceAndroidConfigEditReq request) {
        DeviceAndroidConfigDTO configDTO = this.converter.updateReq2Dto(request);
        // 更新主表数据
        this.update(configDTO) ;

        // 如果是全量发布, 配置所有设备
        if (ReleaseTypeEnum.ALL.getCode().equals(request.getReleaseType())) {
            DeviceDO deviceQueryParam = new DeviceDO();
            deviceQueryParam.setIsMaster(CommonConstants.ONE);

            List<DeviceDO> allMasterDevice = this.deviceService.findByModel(deviceQueryParam, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
            List<Long> deviceIds = allMasterDevice.stream().map(DeviceDO::getId).collect(Collectors.toList());
            request.setRelatedDevice(deviceIds);
        } else if (CollectionUtils.isEmpty(request.getRelatedDevice())) {
            this.deviceConfigRowService.removeByConfigId(request.getId());
        }

        if (!CollectionUtils.isEmpty(request.getRelatedDevice())) {
            List<DeviceConfigRowDO> configRows = request.getRelatedDevice().stream().map(deviceId -> this.service.buildConfigRow(request.getId(), deviceId)).collect(Collectors.toList());
            // 先删除，再添加
            this.deviceConfigRowService.removeByConfigId(request.getId());
            this.deviceConfigRowService.addBatch(configRows);
        }

        return true;
    }

    public AndroidConfigVO pull(String md5, String imei) {

        DeviceDO device = this.deviceService.getDeviceByImei(imei);

        if (device == null) {
            return new AndroidConfigVO(md5, Collections.emptyList());
        }

        List<DeviceAndroidConfigDO> configDOS = this.service.getAllConfigs(device.getId());
        List<AndroidConfigVO.KeyValue> dataList = new ArrayList<>();
        configDOS.forEach(f -> {
            AndroidConfigVO.KeyValue keyValue = new AndroidConfigVO.KeyValue();
            keyValue.setKey(f.getKey());
            keyValue.setValue(f.getValue());
            dataList.add(keyValue);
        });

        String newMd5 = SignUtil.signWithMd5(JsonUtil.stringify(dataList));

        return md5.equals(newMd5) ? new AndroidConfigVO(newMd5, Collections.emptyList()) : new AndroidConfigVO(newMd5, dataList);
    }
}

